package org.melanesia.dom;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 * Quite naive, but so far sufficient ;-) read only DOM wrapper.
 *
 * @author marcin.kielar
 */
public class Node {

    /** Wrapped w3c node. */
    private final org.w3c.dom.Node thisNode;

    /**
     * Constructs node from input stream.
     * @param inputStream input stream to parse
     * @throws SAXException  If any parse errors occur.
     * @throws IOException If any IO errors occur.
     * @throws ParserConfigurationException if a DocumentBuilder cannot be created which satisfies the configuration requested.
     */
    public Node(final InputStream inputStream) throws SAXException, IOException, ParserConfigurationException {
        Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(inputStream);
        thisNode = document.getDocumentElement();
    }

    /**
     * Constructs node from w3c node.
     * @param node w3c node
     */
    public Node(final org.w3c.dom.Node node) {
        thisNode = node;
    }

    /**
     * Returns all child elements of this node.
     * @return list child elements
     */
    public final List<Node> getChildren() {

        NodeList nodeList = thisNode.getChildNodes();
        List<Node> children = new ArrayList<Node>(nodeList.getLength());

        for (int i = 0, size = nodeList.getLength(); i < size; i++) {
            org.w3c.dom.Node item = nodeList.item(i);
            if (item.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
            	children.add(new Node(item));
            }
        }

        return children;
    }

    /**
     * Returns all child elements of given name.
     * @param nodeName name of the elements to return
     * @return list child elements
     */
    public final List<Node> getChildren(final String nodeName) {

        NodeList nodeList = thisNode.getChildNodes();
        List<Node> children = new ArrayList<Node>(nodeList.getLength());

        for (int i = 0, size = nodeList.getLength(); i < size; i++) {
            org.w3c.dom.Node item = nodeList.item(i);
            if (item.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE && item.getNodeName().equals(nodeName)) {
                children.add(new Node(item));
            }
        }

        return children;
    }

    /**
     * Returns this node name.
     * @return node name
     */
    public final String getNodeName() {
        return thisNode.getNodeName();
    }

    /**
     * Returns attribute value.
     * @param name attribute name
     * @return attribute value
     */
    public final String getAttribute(final String name) {
        NamedNodeMap map = thisNode.getAttributes();
        org.w3c.dom.Node attrNode = map.getNamedItem(name);
        if (attrNode != null) {
            return attrNode.getTextContent();
        } else {
            return null;
        }
    }

    /**
     * Returns node text content.
     * @return node text content
     */
    public final String getTextContent() {
        return thisNode.getTextContent();
    }

    @Override
	public final String toString() {
    	return thisNode.getNodeName();
    }

}
